﻿#region

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using VinhSon.Intranet.Bussiness;
using VinhSon.Intranet.Models.Security;

#endregion

namespace VinhSon.Intranet.Models
{
    public class AppUtil
    {
        public const string PERMISSION_LIST = "PERMISSION_LIST";

        public const string USER_LIST = "USER_LIST";

        public static CustomAuthorizeContext AuthorizeContext = new CustomAuthorizeContext();

        public static bool ResetAuthenticationService { get; set; }

        public static bool ResetUserAuthenticationService { get; set; }

        public static List<string> Users { get; set; }

        public static void InitializePermission(HttpApplicationState application)
        {
            Dictionary<int, string> dictionaryPermission = InitializePermissions();
            application[PERMISSION_LIST] = dictionaryPermission;
            ResetAuthenticationService = false;
        }

        public static void InitializePermission(HttpApplicationStateBase application)
        {
            Dictionary<int, string> dictionaryPermission = InitializePermissions();
            application[PERMISSION_LIST] = dictionaryPermission;
            ResetAuthenticationService = false;
        }

        public static void InitializePermission(HttpApplicationStateBase application,
                                                UnitOfWork unitOfWork,
                                                int? applicationId)
        {
            if (applicationId.HasValue)
            {
                Dictionary<int, string> dictionaryPermission = InitializePermissions(unitOfWork);
                application[PERMISSION_LIST] = dictionaryPermission;
            }
        }

        private static Dictionary<int, string> InitializePermissions()
        {
            UnitOfWork unitOfWork = new UnitOfWork();
            return InitializePermissions(unitOfWork);
        }

        private static Dictionary<int, string> InitializePermissions(UnitOfWork unitOfWork)
        {
            List<Permission> permissions = unitOfWork.PermissionRepository.Select()
                                                     .Where(c => c.Inactive == false)
                                                     .Select(c => c)
                                                     .ToList();
            Dictionary<int, string> dictionaryPermission = new Dictionary<int, string>();
            foreach (Permission permission in permissions)
            {
                if (!string.IsNullOrEmpty(permission.KeyName))
                    dictionaryPermission.Add(permission.Id,
                                             permission.KeyName);
            }
            return dictionaryPermission;
        }

        public static void InitializeUser(HttpApplicationState application)
        {
            application[USER_LIST] = new Dictionary<string, BitArray>();
            ResetUserAuthenticationService = false;
        }

        public static void InitializeUser(HttpApplicationStateBase application)
        {
            application[USER_LIST] = new Dictionary<string, BitArray>();
            ResetUserAuthenticationService = false;
        }

        public static void InitializeUser(HttpApplicationStateBase application,
                                          string userName,
                                          UnitOfWork unitOfWork)
        {
            Dictionary<int, string> dictionaryPermission;
            Dictionary<string, BitArray> listUsers;
            CheckInitialPermission(application,
                                   out listUsers,
                                   out dictionaryPermission);
            InitializeUser(listUsers,
                           dictionaryPermission,
                           userName,
                           unitOfWork);
        }

        public static void InitializeUser(HttpApplicationState application,
                                          string userName,
                                          UnitOfWork unitOfWork)
        {
            Dictionary<int, string> dictionaryPermission;
            Dictionary<string, BitArray> listUsers;
            CheckInitialPermission(application,
                                   out listUsers,
                                   out dictionaryPermission);
            InitializeUser(listUsers,
                           dictionaryPermission,
                           userName,
                           unitOfWork);
        }

        public static BitArray InitializeUser(Dictionary<string, BitArray> listUsers,
                                              Dictionary<int, string> dictionaryPermission,
                                              string userName)
        {
            UnitOfWork unitOfWork = new UnitOfWork();
            return InitializeUser(listUsers,
                                  dictionaryPermission,
                                  userName,
                                  unitOfWork);
        }

        private static BitArray InitializeUser(Dictionary<string, BitArray> listUsers,
                                               Dictionary<int, string> dictionaryPermission,
                                               string userName,
                                               UnitOfWork unitOfWork)
        {
            User user = unitOfWork.UserRepository.Select(c => c.Username.Equals(userName,
                                                                                      StringComparison.InvariantCultureIgnoreCase),
                                                               "Roles.Permissions,UserGroups.Permissions")
                                        .FirstOrDefault();
            if (user == null)
                return null;
            if ((user.Inactive ?? false))
                return null;
            int maxId = 0;
            if (dictionaryPermission.Any())
                maxId = dictionaryPermission.Keys.Max();
            BitArray bitArray = new BitArray(maxId);
            for (int i = 0; i < maxId; i++)
            {
                bitArray[i] = false;
            }
            foreach (int index in
                    user.Roles.Where(c => c.Inactive == false)
                        .SelectMany(c => c.Permissions.Where(v => v.Inactive == false),
                                    (t,
                                     v) => v.Id)
                        .Distinct())
            {
                bitArray[index - 1] = true;
            }
            foreach (int index in
                    user.UserGroups.Where(c => c.Inactive == false)
                        .SelectMany(c => c.Permissions.Where(v => v.Inactive == false),
                                    (t,
                                     v) => v.Id)
                        .Distinct())
            {
                bitArray[index - 1] = true;
            }
            listUsers[userName] = bitArray;
            return bitArray;
        }

        public static void CheckInitialPermission(HttpApplicationStateBase application,
                                                  out Dictionary<string, BitArray> listUsers,
                                                  out Dictionary<int, string> dictionaryPermission)
        {
            if (ResetAuthenticationService)
            {
                application[PERMISSION_LIST] = null;
                application[USER_LIST] = null;
            }

            dictionaryPermission = application[PERMISSION_LIST] as Dictionary<int, string>;
            listUsers = application[USER_LIST] as Dictionary<string, BitArray>;

            if (ResetUserAuthenticationService)
                ResetUserAuthentication(listUsers);

            bool initialize = false;
            if (dictionaryPermission == null)
            {
                initialize = true;
                lock (application)
                {
                    InitializePermission(application);
                }
            }
            if (listUsers == null)
            {
                initialize = true;
                lock (application)
                {
                    InitializeUser(application);
                }
            }
            if (initialize)
                CheckInitialPermission(application,
                                       out listUsers,
                                       out dictionaryPermission);
        }

        public static void CheckInitialPermission(HttpApplicationState application,
                                                  out Dictionary<string, BitArray> listUsers,
                                                  out Dictionary<int, string> dictionaryPermission)
        {
            if (ResetAuthenticationService)
            {
                application[PERMISSION_LIST] = null;
                application[USER_LIST] = null;
            }

            dictionaryPermission = application[PERMISSION_LIST] as Dictionary<int, string>;
            listUsers = application[USER_LIST] as Dictionary<string, BitArray>;

            if (ResetUserAuthenticationService)
                ResetUserAuthentication(listUsers);

            bool initialize = false;
            if (dictionaryPermission == null)
            {
                initialize = true;
                lock (application)
                {
                    InitializePermission(application);
                }
            }
            if (listUsers == null)
            {
                initialize = true;
                lock (application)
                {
                    InitializeUser(application);
                }
            }
            if (initialize)
                CheckInitialPermission(application,
                                       out listUsers,
                                       out dictionaryPermission);
        }

        private static void ResetUserAuthentication(Dictionary<string, BitArray> listUsers)
        {
            if (listUsers == null)
                return;

            lock (Users)
            {
                List<string> temp = new List<string>(Users);
                Users.Clear();
                ResetUserAuthenticationService = false;
                foreach (string item in temp.Where(listUsers.ContainsKey))
                    listUsers.Remove(item);
            }
        }

        public static void UserLogOff(HttpApplicationStateBase application,
                                      string userName)
        {
            Dictionary<string, BitArray> listUsers = application[USER_LIST] as Dictionary<string, BitArray>;
            if (listUsers != null)
            {
                if (listUsers.ContainsKey(userName))
                {
                    lock (application)
                    {
                        listUsers.Remove(userName);
                    }
                }
            }
        }

        public static void UserLogOff(HttpApplicationStateBase application,
                                      IEnumerable<string> userList)
        {
            foreach (string s in userList)
            {
                UserLogOff(application,
                           s);
            }
        }
       
    }
}
